import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:flutter_note/note/bean.dart';
import 'package:flutter_note/note/const.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

//系统工具
class SystemUtils {
  /*获取屏幕宽度*/
  static double getScreenWidth(BuildContext context) {
    return MediaQuery.of(context).size.width;
  }

  /*获取屏幕高度*/
  static double getScreenHeight(BuildContext context) {
    return MediaQuery.of(context).size.height;
  }

  /*获取系统状态栏高度*/
  static double getSysStatsHeight(BuildContext context) {
    return MediaQuery.of(context).padding.top;
  }
}

//Date格式化
class DateUtils {
  static String msToYMDHm(int ms) {
    var time = DateTime.fromMillisecondsSinceEpoch(ms);
    return "${time.year}-${time.month}-${time.day} ${zeroFormat(time.hour)}:${zeroFormat(time.minute)}";
  }

  static String msToYMD(int ms) {
    var time = DateTime.fromMillisecondsSinceEpoch(ms);
    return "${time.year}-${time.month}-${time.day}";
  }

  static String msToHm(int ms) {
    var time = DateTime.fromMillisecondsSinceEpoch(ms);
    return "${zeroFormat(time.hour)}:${zeroFormat(time.minute)}";
  }

  static String zeroFormat(int time) {
    return time < 10 ? '0$time' : '$time';
  }
}

class EncryptUtils {
  // md5 32位加密
  static String md5e(String data) {
    var content = new Utf8Encoder().convert(data);
    var digest = md5.convert(content);
    // 这里其实就是 digest.toString()
    return hex.encode(digest.bytes).toUpperCase();
  }

  // md5 16位加密
  static String md5x(String data) {
    return md5e(data).substring(8, 24);
  }
}

class EmptyUtils {
  static bool isEmpty(obj) {
    if (obj == null || obj.isEmpty) {
      return true;
    }
    return false;
  }

  static bool isNotEmpty(obj) {
    if (obj == null || obj.isEmpty) {
      return false;
    }
    return true;
  }
}

//SP偏好设置
class SPUtils {
  static void setString(key, value) async {
    SharedPreferences sp = await SharedPreferences.getInstance();
    sp.setString(key, value);
    //sp.clear();
  }

  static Future<String> getString(key) async {
    SharedPreferences sp = await SharedPreferences.getInstance();
    String value = sp.getString(key);
    //sp.clear();
    return value;
  }
}

class ImageUtils {
  /*
   *选择相册图片,头像像素为188且可以剪裁,普通图片为640
   * isHead  true:需要剪裁 false:不需要剪裁
   */
  static Future<File> pickImage(bool isHead) async {
    var pickImage = await ImagePicker.pickImage(source: ImageSource.gallery);
    File image = pickImage;
    if (isHead) {
      image = await ImageCropper.cropImage(
        sourcePath: pickImage.path,
        ratioX: 1.0,
        ratioY: 1.0,
        maxWidth: Const.IMG_SIZE_HEAD,
        maxHeight: Const.IMG_SIZE_HEAD,
        toolbarTitle: 'Cropper',
        toolbarColor: Colors.green,
      );
    }
    if (image == null || !image.path.contains('.')) {
      return null;
    }
    if (isHead) {
      return await ImageUtils.compressImage(image, Const.IMG_SIZE_HEAD);
    } else {
      return await ImageUtils.compressImage(image, Const.IMG_SIZE_PIC);
    }
  }

  /*
 *压缩图片
 * rawImage 原图片
 * targetPath 目标名称
 */
  static Future<File> compressImage(File rawImage, int size) async {
    //获取后缀
    String suffix = rawImage.path.substring(rawImage.path.lastIndexOf('.') + 1);
    //压缩图标,并且为md5名字
    String md5File =
        EncryptUtils.md5x(rawImage.path + DateTime.now().toString());

    Directory tempDir = await getTemporaryDirectory();
    String tempPath = tempDir.path;
    String compPath = "$tempPath/$md5File.$suffix";
    var result = await FlutterImageCompress.compressAndGetFile(
        rawImage.absolute.path, compPath,
        quality: 80, minHeight: size, minWidth: size);
    print(
        "image raw path = $rawImage, size:${rawImage.lengthSync()}==>comp path:${compPath}, size:${result.lengthSync()}");
    return result;
  }
}

//Dio网络请求
class HttpUtils {
  static Options options = Options(
    baseUrl: Const.BASE_HOST,
    connectTimeout: 10000,
    receiveTimeout: 10000,
  );
  static Dio dio = Dio(options);

  static Future<Reply> post(Map<String, dynamic> map, apiUrl) async {
    print(
        "==>Dio Post请求:" + Const.BASE_HOST + apiUrl + " 参数:" + map.toString());
    FormData formData = FormData.from(map);
    try {
      var response = await dio.post(apiUrl, data: formData);
      var reply = Reply();
      reply = Reply.fromJson(response.data);
      print("<==Dio返回:" + reply.toString());
      return reply;
    } catch (e) {
      print(e);
      var reply = Reply();
      if (e.toString().contains('errno = 101')) {
        reply.code = Const.NET_ERROR;
        reply.msg = "网络失败,请检查网络";
      } else if (e.toString().contains('errno = 111')) {
        reply.code = Const.SERVER_ERROR;
        reply.msg = "连接不到服务器";
      } else if (e.toString().contains('errno = 113')) {
        reply.code = Const.SERVER_ERROR;
        reply.msg = "连接不到服务器";
      } else {
        reply.code = Const.SERVER_ERROR;
        reply.msg = "数据异常";
      }
      print("<==Dio catch返回:" + reply.toString());
      return reply;
    }
  }

  static Future<Reply> get(Map<String, dynamic> map, apiUrl) async {
    print("==>Dio Get请求:" + Const.BASE_HOST + apiUrl + " 参数:" + map.toString());
    FormData formData = FormData.from(map);
    try {
      var response = await dio.get(apiUrl, data: formData);
      var reply = Reply();
      reply = Reply.fromJson(response.data);
      print("<==Dio 返回:" + reply.toString());
      return reply;
    } catch (e) {
      print(e);
      var reply = Reply();
      if (e.toString().contains('errno = 101')) {
        reply.code = Const.NET_ERROR;
        reply.msg = "网络失败,请检查网络";
      } else if (e.toString().contains('errno = 111')) {
        reply.code = Const.SERVER_ERROR;
        reply.msg = "连接不到服务器";
      }
      print("<==Dio catch返回:" + reply.toString());
      return reply;
    }
  }
}

//HTTP网络请求
/*class HttpUtils {
  static Future<Reply> post(Map<String, String> map, apiUrl) async {
    String dataURL = Const.BASE_HOST + apiUrl;
    print("==>Post请求:" + dataURL + " 参数:" + map.toString());
    try {
      http.Response response = await http.post(dataURL, body: map);
      var reply = Reply();
      reply = Reply.fromJson(json.decode(response.body));
      print("<==返回:" + reply.toString());
      return reply;
    } catch (e) {
      print(e);
      var reply = Reply();
      if (e.toString().contains('errno = 101')) {
        reply.code = Const.NET_ERROR;
        reply.msg = "网络失败,请检查网络";
      } else if (e.toString().contains('errno = 111')) {
        reply.code = Const.SERVER_ERROR;
        reply.msg = "连接不到服务器";
      }
      print("<==catch返回:" + reply.toString());
      return reply;
    }
  }

  static Future<Reply> get(Map<String, String> map, apiUrl) async {
    var params = "?";
    map.forEach((key, value) {
      params = "$params$key=$value&";
    });
    params = params.substring(0, params.length - 1);
    String dataURL = Const.BASE_HOST + apiUrl + params;
    print("==>Get请求:" + dataURL);
    try {
      http.Response response = await http.get(dataURL);
      var reply = Reply();
      reply = Reply.fromJson(json.decode(response.body));
      print("<==返回:" + reply.toString());
      return reply;
    } catch (e) {
      print(e);
      var reply = Reply();
      if (e.toString().contains('errno = 101')) {
        reply.code = Const.NET_ERROR;
        reply.msg = "网络失败,请检查网络";
      } else if (e.toString().contains('errno = 111')) {
        reply.code = Const.SERVER_ERROR;
        reply.msg = "连接不到服务器";
      }
      print("<==catch返回:" + reply.toString());
      return reply;
    }
  }
}*/
